#include "DList.h"

// create a new node
LTNode *Buy_LTNode(LTDataType x)
{
    LTNode *pnode = malloc(sizeof(LTNode));
    if (pnode == NULL) 
    {
        perror("malloc failed");
        exit(1);
    }
    pnode->data = x;
    pnode->prev = NULL;
    pnode->next = NULL;
    return pnode;
}

// Print List
void LTPrint(LTNode *phead)
{
    assert(phead);
    LTNode *pcur = phead->next;
    printf("head-->");
    while (pcur != phead)
    {
        printf("%d-->", pcur->data);
        pcur = pcur->next;
    }
    printf("head\n");
}

// 在链表里顺序查找到第一个值为x的节点
LTNode *LTFind(LTNode *phead, LTDataType x)
{
    assert(phead);
    assert(phead != phead->next);
    LTNode *pcur = phead->next;
    while (pcur != phead)
    {
        if (pcur->data == x)
        {
            return pcur;
        }
        pcur = pcur->next;
    }
    return NULL;
}

// init a dummy head node into the List
LTNode *LTInit(void)
{
    LTNode* phead = Buy_LTNode(-1);
    phead->next = phead->prev = phead;
    return phead;
}

// destory List
    
// void LTDestory(LTNode **pphead)
// 推荐使用一级 -->保持接口一致性 其他函数都是一级 但是要在主函数里把指针置为空,内容已经被释放了
void LTDestory(LTNode *phead)
{
    assert(phead);
    
    LTNode *pcur = phead->next;

    while (pcur != phead)
    {
        LTNode *next = pcur->next;
        free(pcur);
        pcur = next;
    }
    // 只剩哨兵位没有清除了
    free(phead);
    phead = NULL;
}


// 头插
void LTPushFront(LTNode *phead, LTDataType x)
{
    LTNode *newnode = Buy_LTNode(x);
    newnode->prev = phead;
    newnode->next = phead->next;

    phead->next->prev = newnode;

    phead->next = newnode;
}


void LTPushBack(LTNode *phead, LTDataType x)
{
    LTNode *newnode = Buy_LTNode(x);
    newnode->prev = phead->prev;
    newnode->next = phead;

    phead->prev->next = newnode;

    phead->prev = newnode;
}       

// 指定位置之后插入
void LTInsertAfter(LTNode *pnode, LTDataType x)
{
    LTNode *newnode = Buy_LTNode(x);
    newnode->prev = pnode;
    newnode->next = pnode->next;

    pnode->next->prev = newnode;

    pnode->next = newnode;   
}


// 指定位置之前插入
void LTInsertBefore(LTNode *pnode, LTDataType x)
{
    LTNode *newnode = Buy_LTNode(x);
    newnode->prev = pnode->prev;
    newnode->next = pnode;

    pnode->prev->next = newnode;

    pnode->prev = newnode;   
}

// 删除数据
// 尾删
void LTPopBack(LTNode *phead)
{
    assert(phead);
    // 链表不能为空
    assert(phead != phead->next);
    // 存储要free的节点
    LTNode *del = phead->prev;
    LTNode *prev = del->prev;

    prev->next = phead;
    phead->prev = prev;
    // 释放尾节点
    free(del);
    del = NULL;
}
// 头删
void LTPopFront(LTNode *phead)
{
    assert(phead);
    // 链表不为空
    assert(phead != phead->next);
    LTNode *del = phead->next;
    LTNode *next = del->next;

    next->prev = phead;
    phead->next = next;

    // 释放头节点
    free(del);
    del = NULL;
}


// 指定位置删除
void LTErase(LTNode *pnode)
{
    assert(pnode);
    // 链表不为空
    assert(pnode != pnode->next);

    LTNode *prev = pnode->prev;
    LTNode *next = pnode->next;

    prev->next = next;
    next->prev = prev;

    free(pnode);
    pnode = NULL;
}